/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.treepoke.util.ftp;

import com.treepoke.util.exception.UtilException;
import com.treepoke.util.logging.CRCCLogger;
import com.treepoke.util.properties.TPConstant;
import java.io.*;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

public class FTPUtil {
    
    private FTPClient ftpClient;
    private static FTPUtil instance;
    private CRCCLogger logger = CRCCLogger.getLogger(TPConstant.getNOMBRE_APLICACION());
    
    private FTPUtil(){
        ftpClient = new FTPClient();
    }
    
    public static FTPUtil getInstance() throws UtilException {
        if (instance == null) {
            instance = new FTPUtil();
        }

        return instance;
    }
    
    /**
     * @param host
     * @param port
     * @param user
     * @param password
     * @author etorres
     */
    public void connect(String host, int port, String user, String password) throws UtilException {
        try {
            ftpClient.connect(host, port);
            ftpClient.login(user, password);
            ftpClient.enterLocalPassiveMode();
            logger.infoMessage("FTP conectado " + host + ":" + port + ", user = " + user);
            
            int reply = ftpClient.getReplyCode();

            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                throw new UtilException("El servidor FTP rechazó la conexión", 0);
            }            
        } catch (SocketException ex) {
            throw new UtilException("Error conectando FTP " + host + ":" + port + 
                ", user = " + user, ex, 0);
        } catch (IOException ex) {
            throw new UtilException("Error conectando FTP " + host + ":" + port + 
                ", user = " + user, ex, 0);
        }        
    }
    
    public void disconnect() throws UtilException {
        try {
            if (ftpClient.isConnected()) {
                ftpClient.logout();
                ftpClient.disconnect();
            }
            logger.infoMessage("FTP desconectado");
        } catch (IOException ex) {
            throw new UtilException("Error desconectando FTP", ex, 0);
        }        
    }    

    /**
     * @param localFile
     * @param remoteFile
     * @author etorres
     */
    public void uploadFile(File localFile, String remoteFile) throws UtilException {
        InputStream inputStream = null;
        try {
            logger.infoMessage("Inicia subida de archivo " + localFile.getName());
            inputStream = new FileInputStream(localFile);
            boolean done = ftpClient.storeFile(remoteFile, inputStream);
            if (done) {
                logger.infoMessage("El archivo " + localFile.getName() + " se subió correctamente.");
            }
            else {
                logger.infoMessage("El archivo " + localFile.getName() + " NO se subió correctamente, favor verifique.");
            }
        } catch (FileNotFoundException ex) {
            throw new UtilException("Error con archivo: " + localFile.getName(), ex, 0);
        } catch (IOException ex) {
            throw new UtilException("Error de I/O", ex, 0);
        } finally {
            try {
                inputStream.close();
            } catch (IOException ex) {
                throw new UtilException("Error cerrando stream", ex, 0);
            }
        }
    }
    
    /**
     * @param localFile
     * @param remoteFile
     * @author etorres
     */
    public void downloadFile(File localFile, String remoteFile) throws UtilException {
        OutputStream outputStream = null;
        try {
            logger.infoMessage("Inicia bajada de archivo " + remoteFile);
            outputStream = new FileOutputStream(localFile);
            boolean done = ftpClient.retrieveFile(remoteFile, outputStream);
            if (done) {
                logger.infoMessage("El archivo " + remoteFile + " se bajó correctamente.");
            }
            else {
                logger.infoMessage("El archivo " + remoteFile + " NO se bajó correctamente, favor verifique.");
            }
        } catch (FileNotFoundException ex) {
            throw new UtilException("Error con archivo: " + localFile.getName(), ex, 0);
        } catch (IOException ex) {
            throw new UtilException("Error de I/O", ex, 0);
        } finally {
            try {
                outputStream.close();
            } catch (IOException ex) {
                throw new UtilException("Error cerrando stream", ex, 0);
            }
        }
    }    
    
    /**
     * @param binary
     * @author etorres
     */
    public void setFileType(boolean binary) throws UtilException {
        try {
            ftpClient.setFileType((binary)? FTP.BINARY_FILE_TYPE : FTP.ASCII_FILE_TYPE);
        } catch (IOException ex) {
            throw new UtilException("Error asignando tipo de archivo", ex, 0);
        }         
    }
    
    /**
     * @param directory
     * @throws UtilException 
     */
    public void changeWorkingDirectory(String directory) throws UtilException {
        try {
            ftpClient.changeWorkingDirectory(directory);
        } catch (IOException ex) {
            throw new UtilException("Error cambiando el directorio de trabajo", ex, 0);
        }         
    }
   
}
